/*
 * kernel/interrupt.S
 *
 * last modified by ChenJie at 2007.07.15
 *
 */

#include <asm/asmdef.h>
#include <asm/i386.h>

/*
  *	exception and trap has the highest priority, 
  *   and the NMI interrupt is the middle,
  *   while, the INTR interrupt has the lowest priority.
  *
  */
  
// 系统调用的个数:
#define nr_system_calls	((syscall_table_size)/4)

.text
ENTRY(unknown_interrupt)	//处理未识别的中断
	pushl	$-1
	jmp	no_error_code

// int 0
ENTRY(exception00)
	pushl	$0
	jmp	no_error_code

// int 1
ENTRY(exception01)
	pushl	$1
	jmp	no_error_code

// int 2
ENTRY(exception02)
	pushl	$2
	jmp	no_error_code

// int 3
ENTRY(exception03)
	pushl	$3
	jmp	no_error_code

// int 4
ENTRY(exception04)
	pushl	$4
	jmp	no_error_code

// int 5
ENTRY(exception05)
	pushl	$5
	jmp	no_error_code

// int 6
ENTRY(exception06)
	pushl	$6
	jmp	no_error_code

// int 7
ENTRY(exception07)
	pushl	$7
	jmp	no_error_code

// int 8
ENTRY(exception08)
	pushl	$8
	jmp	error_code

// int 9
ENTRY(exception09)
	pushl	$9
	jmp	no_error_code

// int 10
ENTRY(exception10)
	pushl	$10
	jmp	error_code

// int 11
ENTRY(exception11)
	pushl	$11
	jmp	error_code

// int 12
ENTRY(exception12)
	pushl	$12
	jmp	error_code

// int 13
ENTRY(exception13)
	pushl	$13
	jmp	error_code

// int 14
ENTRY(exception14)
	pushl	$14
	jmp	no_error_code

// int 15
ENTRY(exception15)
	pushl	$15
	jmp	no_error_code

// int 16
ENTRY(exception16)
	pushl	$16
	jmp	no_error_code

// for hardware interrupt which from i8259 master and slave.
ENTRY(hwint00) 
	pushl	$0
	jmp	interrupt

ENTRY(hwint01) 
	pushl	$1
	jmp	interrupt

ENTRY(hwint02) 
	pushl	$2
	jmp	interrupt

ENTRY(hwint03) 
	pushl	$3
	jmp	interrupt

ENTRY(hwint04) 
	pushl	$4
	jmp	interrupt

ENTRY(hwint05) 
	pushl	$5
	jmp	interrupt

ENTRY(hwint06) 
	pushl	$6
	jmp	interrupt

ENTRY(hwint07) 
	pushl	$7
	jmp	interrupt

ENTRY(hwint08) 
	pushl	$8
	jmp	interrupt

ENTRY(hwint09) 
	pushl	$9
	jmp	interrupt

ENTRY(hwint10) 
	pushl	$10
	jmp	interrupt

ENTRY(hwint11) 
	pushl	$11
	jmp	interrupt

ENTRY(hwint12) 
	pushl	$12
	jmp	interrupt

ENTRY(hwint13) 
	pushl	$13
	jmp	interrupt

ENTRY(hwint14) 
	pushl	$14
	jmp	interrupt

ENTRY(hwint15) 
	pushl	$15
	jmp	interrupt

// for all processes
ENTRY(ipc_call) 
	pushl	$1
	jmp	syscall
	
// only for system processes
ENTRY(system_call) 
	pushl	$0
	jmp	syscall



no_error_code:
	xchgl	%eax, (%esp)	// exception_nr <---> eax
	pushl	%ebx
	pushl	%ecx
	pushl	%edx
	pushl	%edi
	pushl	%esi
	pushl	%ebp
	push	%ds
	push	%es
	push	%fs
	push	%gs

	lea	(%esp), %ebp	// pointer of the kstack-struct
	pushl	$0		// 把0当作错误号入栈
	pushl	%eax
	pushl	%ebp

	jmp		exception
	
error_code:
	xchgl	%eax, 4(%esp)	//此时error code <---> eax
	xchgl	%ebx, (%esp)	// exception_nr <---> ebx
	pushl	%ecx
	pushl	%edx
	pushl	%edi
	pushl	%esi
	pushl	%ebp
	push	%ds
	push	%es
	push	%fs
	push	%gs

	lea	(%esp), %ebp	// pointer of the kstack-struct
	pushl	%eax		// error code -->stack
	pushl	%ebx
	pushl	%ebp

exception:
	movw	$SELECTOR_KDS, %ax
	movw	%ax, %ds
	movw	%ax, %es
	movw	$SELECTOR_UDS, %ax
	movw	%ax, %fs
	movw	$SELECTOR_KGS, %ax
	movw	%ax, %gs
	call	do_exception;  # do_exception(kstack, exception_nr, error_code)
	addl	$12, %esp
	jmp		ret_from_interrupt

interrupt:
	xchgl	%eax, (%esp)	// exception_nr <---> eax
	pushl	%ebx
	pushl	%ecx
	pushl	%edx
	pushl	%edi
	pushl	%esi
	pushl	%ebp
	push	%ds
	push	%es
	push	%fs
	push	%gs

	lea	(%esp), %ebp	// entry-point of the kstack-struct
	pushl	%eax
	pushl	%ebp

	movw	$SELECTOR_KDS, %ax
	movw	%ax, %ds
	movw	%ax, %es
	movw	$SELECTOR_UDS, %ax
	movw	%ax, %fs
	movw	$SELECTOR_KGS, %ax
	movw	%ax, %gs
	call	do_interrupt   # do_interrupt(kstack, intr)
	addl	$8, %esp
	jmp		ret_from_interrupt

syscall:
	xchgl	%eax, (%esp)	// call_type <---> eax
	pushl	%ebx
	pushl	%ecx
	pushl	%edx
	pushl	%edi
	pushl	%esi
	pushl	%ebp
	push	%ds
	push	%es
	push	%fs
	push	%gs		// offset of the kstack_struct

	lea	(%esp), %ebp	// kstack address --> %ebp
	pushl	%eax
	pushl	%ebp		// as the nearest argument

	movw	$SELECTOR_KDS, %ax
	movw	%ax, %ds
	movw	%ax, %es
	movw	$SELECTOR_UDS, %ax
	movw	%ax, %fs
	movw	$SELECTOR_KGS, %ax
	movw	%ax, %gs
	call	do_syscall   # do_syscall(kstack, type)
	addl	$8, %esp
	jmp		ret_from_interrupt
	
ret_from_interrupt:
	pop	%gs
	pop	%fs
	pop	%es
	pop	%ds
	popl	%ebp
	popl	%esi
	popl	%edi
	popl	%edx
	popl	%ecx
	popl	%ebx
	popl	%eax
	iret


.data
ENTRY(sys_call_table)
#include "syscall_table.S"
syscall_table_size = (. - sys_call_table)
